using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace Program
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Stopwatch sw = new ();
            Console.WriteLine(Environment.ProcessorCount);
            sw.Start();
            for (int i = 0; i < 30; i++)
            {
                int index = i;
                Flos.Threading.ThreadPool.Run(() => IncrementRes());
            }
            Console.WriteLine("All tasks pushed to queue");
            Flos.Threading.ThreadPool.WhenAll();
            Console.WriteLine("All tasks done");
            Console.Write("List: ");
            {
                var lst = bag.ToList();
                lst.SortLink().Print();
            }
            sw.Stop();


            Console.WriteLine($"Elapsed time: {sw.ElapsedMilliseconds} ms");

        }


        public static void HeavyJob(int i)
        {
            Thread.Sleep(5000);
            Console.WriteLine($" Thread {Environment.CurrentManagedThreadId} - Job {i} Done");
        }

        public static int res = 0;
        private static object _resLock = new();

        private static ConcurrentBag<int> bag = new();


        public static void IncrementRes()
        {
            int newVal = Interlocked.Increment(ref res);
            Thread.Sleep(100);
            bag.Add(newVal);
            Console.WriteLine($"Thread {Environment.CurrentManagedThreadId} done at {DateTime.Now.ToString("HH:mm:ss.fff")} - res: {newVal}");   
        }
    }

    public static class ListExtensions
    {
        public static void Print<T>(this List<T> lst)
        {
            foreach(T elem in lst)
            {
                Console.Write($"{elem} ");
            }
            Console.Write("\n");
        }

        public static List<T> SortLink<T>(this List<T> lst) where T : IComparable
        {
            lst.Sort();
            return lst;
        }
    }

    public static class ConcurrentBag
    {
        public static void Print<T>(this ConcurrentBag<T> x)
        {
            foreach(T elem in x)
            {
                Console.Write($"{elem} ");
            }
            Console.WriteLine("\n");
        }
    }
}